local skynet = require "skynet"
local util = require "util"
local constant = require "constant"
local utils = require "utils"
require "luaext"

local table_unpack = table.unpack
local table_insert = table.insert
local math_random = math.random
local math_floor  = math.floor
local math_ceil   = math.ceil
local table_remove = table.remove

local M = {}

local Methods = {}
local MT = {
    __index = Methods
}

local function copy_table(t)
    local new_t = {}

    for k,v in pairs(t) do
        new_t[k] = v
    end

    return new_t
end

function M.new(uid,player_info,robot_type,addr,fd,coins_type)
    local o = {
        uid = uid,
        player_info = player_info,
        addr = addr,
        fd = fd,
        start_time = util.get_now_time(),
        robot_type = robot_type,
        life_duration  = math_random(5 * 60, 60 * 60), --机器人生命周期 10分钟~60分钟
        coins_type = coins_type, -- 1:非R型机器人 2：小R型机器人 3:中R型机器人 4：大R型机器人 5：土豪型机器人
        on_exiting = false,--正在退出
        --time_bet = {},
        begin_bet_time = 0,
        --stage_bet_coins = {},
        bet_coins_list = {},
    }

    return setmetatable(o, MT)
end

function Methods:on_register(uid)
    if uid ~= self.uid then
        return
    end
--    print("Methods:on_register",self.fd)
    local rob_info = {
        client_version  = '',
        channel         = '',
        cur_channel     = '',
        device_id       = '',
        device_brand    = '',
    }
    skynet.send(self.addr,'lua','enter',self.uid,self.fd,rob_info)
end

--游戏开始触发
function Methods:on_start(game_instance,robot_bet_coins,robot_total_coins_type)
    if self.on_exiting then --正在退出
        return
    end
    
    if not robot_bet_coins then 
        return
    end

    self.game_instance = game_instance
    self.bet_count = 0 --跟注情况
    --self.next_check_time = util.get_now_time() + 1
    self.bet_count_limit = math_random(2,4)
    self.start_bet_time = util.get_now_time()

    local player_info = self.player_info
    local side_bet_coins = robot_bet_coins[player_info.coins_type]
    --这类机器人下注的总额度
    if not side_bet_coins or side_bet_coins == 0 then
        return 
    end
    local robot_total_coins = (robot_total_coins_type[player_info.coins_type] == 0 and not robot_total_coins_type[player_info.coins_type]) and 1 or robot_total_coins_type[player_info.coins_type]

     --确定各区域的下注上限额
     local robot_control = _ENV.global_configs.robot[self.robot_type]
     local robot_cfg = robot_control.robot_type_list[self.coins_type]
--     print("self.coins_type:",self.coins_type,"self.robot_type:",self.robot_type)
     local vip_seat_rate = robot_cfg.vip_seat_rate
     if math_random(1,100) <= vip_seat_rate then
        --请求上座
        self.brnn_will_sit = true
        self.req_sit_time = util.get_now_time() + math_random(1,20)          --随机一个时间入座
        self.sit_position = math_random(1,6)
    end

    self.bet_coins_list = {}
    --self.stage_bet_coins = {}
    --for bet_side = 1, 3 do
    local total_bet_coins = math_floor((self.player_info.coins or 0) / robot_total_coins * side_bet_coins)
    local player_coins = self.player_info.coins
    local bet_coins = self.player_info.available_betting_list[1]
    local index = #self.player_info.available_betting_list --math_random(1, #self.player_info.available_betting_list) 
    while true do
        local k = index
        if k < 1 then
            break
        end
        local tmp_bet_coins = self.player_info.available_betting_list[k]
        if (player_coins >= tmp_bet_coins) and (total_bet_coins >= tmp_bet_coins) then
            table_insert(self.bet_coins_list, tmp_bet_coins)
            player_coins = player_coins - tmp_bet_coins
            total_bet_coins = total_bet_coins - tmp_bet_coins
        else
            index = index - 1
        end
    end
    for k = #self.bet_coins_list, 30 do
        table_insert(self.bet_coins_list, 0)
    end
    table.mix(self.bet_coins_list)
   -- print("tmp_total_coins========22",bet_coins)

   -- print("bbbbbbbbbbbbb",self.total_bet)
    --self.total_bet = bet_coins --个人下注总额
    self.begin_bet_time = util.get_now_time()
    
--    print("bcbm_tmp_total_coins========33",self.uid,tostring_r(self.time_bet))
end

--不是机器人下注的列表，只用于判断机器人是否离开
local function get_robot_leave_bet_list(player_info)
    local bet_list = {}
    for k, coins in pairs(player_info.available_betting_list) do
        if coins <= 100000 then
            table_insert(bet_list,coins)
        end
    end
    return bet_list
end

--游戏结束
function Methods:on_game_over()
 --   dbglog('.................... game over  ...................')
    self.game_instance = nil
    self.bet_count = 0 --跟注情况
    self.next_check_time = nil
    self.side = nil
    self:canBet()     
    --机器人有一定概率的离桌率
    local robot_control = _ENV.global_configs.robot[self.robot_type]
    local robot_cfg = robot_control.robot_type_list[self.player_info.coins_type]
    local leave_rate = robot_cfg.leave_rate or 5
    if math_random(1,100) <= leave_rate then
        skynet.send(self.addr,'lua','REQ_LEAVE',self.uid,{},self.fd)
        self.on_exiting = true
        return
    end 

    local bet_min_limit = 0
    local coins_list = get_robot_leave_bet_list(self.player_info)
    local can_bet
    local player_info = self.player_info
    local curr_coins = player_info.coins
    for _,coins in pairs(coins_list) do
        if curr_coins - coins >= bet_min_limit then
            can_bet = true
            break
        end
    end

    local curr_time = util.get_now_time()
    if curr_time - self.start_time < self.life_duration and can_bet then
        return
    end

    skynet.send(self.addr,'lua','REQ_LEAVE',self.uid,{},self.fd)
    self.on_exiting = true


  --  dbglog(self.uid,'can not bet,exit now',curr_coins)
end

local function get_rand_side(bet_area)
    local total = 0
    for id,count in pairs(bet_area) do
        total = total + tonumber(count)
    end

    local curr = 0
    local rand = math_random(1,total)
    for id,count in pairs(bet_area) do
        curr = curr + tonumber(count)
        if rand <= curr then
            return id
        end
    end
    return math_random(1,#bet_area)
end

function Methods:judge_sit()
    local curr_time = util.get_now_time()
    if self.brnn_will_sit and curr_time > self.req_sit_time and self.sit_position and not self.player_info.position then
        self.brnn_will_sit = false
        return true
    end
    return false
end

function Methods:update_play(curr_time)
    local game_instance = self.game_instance
    if not game_instance then
        return
    end

    if self.on_exiting then --正在退出
        return
    end

    --判断是否到了上座的时间
    if self:judge_sit() then
        skynet.send(self.addr, "lua", "REQ_SITDOWN", self.uid, {position = self.sit_position}, self.fd)
    end

    if not game_instance:is_betting() then
        return
    end

    if not next(self.bet_coins_list) then 
        return 
    end
    if not self:getCanBet() then 
        return 
    end    
    -- if not self.next_check_time then
    --     return
    -- end

    -- if self.bet_count >= self.bet_count_limit then
    --     return
    -- end

    --已经到了检查时间
    -- if curr_time < self.next_check_time then
    --     return
    -- end 
    -- self.next_check_time = util.get_now_time() + math_random(1,5)

     --确定各区域的下注上限额
    local robot_control = _ENV.global_configs.robot[self.robot_type]
    local robot_cfg = robot_control.robot_type_list[self.coins_type]
     --超过了当前时间段所允许的下注额度
     --local total_bet_coins = game_instance:get_total_betting_coins()
     --if total_bet_coins > self.total_bet then
     --    return
     --end

    local side_coins = table_remove(self.bet_coins_list) or 0
    if side_coins <= 0 then
        return
    end
 
    local side = get_rand_side(utils.str_split(robot_cfg.system_bet_area,','))
    --这里做下调整吧，后台配置{红，特殊，黑}，本地为{红，黑，特殊}

    skynet.send(self.addr, "lua", "REQ_BET", self.uid, { side=side, bet_coins = side_coins}, self.fd)
    self.last_bet_time = util.get_now_time()
    --self.stage_bet_coins[time_side] = (self.stage_bet_coins[time_side] or 0) - bet_coins
end

function Methods:on_req_sitdown(uid,position)
    if self.uid == uid then
        self.brnn_will_sit = true
        self.req_sit_time = util.get_now_time() + math_random(1,20)          --随机一个时间入座
        self.sit_position = position
        --skynet.send(self.addr, "lua", "REQ_SITDOWN", self.uid, {position = position}, self.fd)
    end
end

function Methods:update()
    while not self.exit do
        local curr_time = util.get_now_time()

        if self.game_instance then
            --当前可以出牌？
            self:update_play(curr_time)
        end

        skynet.sleep(50)    --500ms
    end
end

function Methods:on_exit()
    --dbglog("robot_on_exit=====",self.uid)
    self.exit = true
    R().robotmgr(1):send('.msg_handler','put_back_robots',{{type=self.robot_type,uid=self.uid,coins=self.player_info.coins}})
end

--是否可以下注
function Methods:canBet()
    --确定各区域的下注上限额
    local robot_control = _ENV.global_configs.robot[self.robot_type]
    local robot_cfg = robot_control.robot_type_list[self.coins_type]    
    --判断可下注的概率
    local rate = robot_cfg.bet_rate or 100
    local rand_num = math_random(1, 100)
    -- print("___canBet_rate____",rand_num, rate)
    if rand_num > rate then 
        self.can_bet = false
        return 
    end
    self.can_bet = true
end

function Methods:getCanBet()
    return self.can_bet
end




return M